home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
lisp
/
eulisp
/
mpfeel.lha
/
MPFeel
/
Modules
/
avl.em
< prev
next >
Wrap
Lisp/Scheme
|
1992-10-06
|
9KB
|
312 lines
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; EuLisp Module Copyright (C) University of Bath 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; File: avl.em
; Title: AVL tree module
; Author: Julian Padget revised Arthur Norman's code.
;
; (c) Copyright 1990, University of Bath, all rights reserved
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Revisions:
; 21-APR-90 (Julian Padget) Code originally comes from Cambridge Lisp and
; was written by Arthur Norman. Mohammed Awdeh and John Fitch made it work
; in PSL and JAP tarted it up with defstruct and modules for EuLisp/PSL
; 10-NOV-90 (Julian Padget) Rewrote instance of avl-prog to let or let*.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defmodule avl
( lists list-operators ccc others macros0 extras0 avl-macros) ()
()
(only
(values-in-tree keys-in-tree avlq-lookup avlq-add avlq-delete)
( avl))
; this holds values for debugging purposes
(deflocal avl-result nil)
; signifies a change in height of the tree
(deflocal changed-height nil)
; Arbitrary comparitor...
(defun avl-lookup (new-key tree)
(unless tree nil)
(avl-lookup1 new-key
(avl-tree-tree tree)
(avl-tree-order tree)
(avl-tree-equality tree)))
(defun avl-add (new-key tree)
(unless tree
(setq tree (make-avl-tree 'order (lambda (a b) nil) 'equality equal)))
((setter avl-tree-tree) tree
(avl-add1 new-key
(avl-tree-tree tree)
(avl-tree-order tree)
(avl-tree-equality tree)))
tree)
; (defun avlr-add (new-key tree)
; (unless tree
; (setq tree (make-avl-tree 'order (lambda (a b) nil) 'equality equal)))
; (avl-add1 new-key tree order (lambda (a b) nil)))
(defun avl-delete (new-key tree)
((setter avl-tree-tree) tree
(avl-delete1 new-key
(avl-tree-tree tree)
(avl-tree-order tree)
(avl-tree-equality tree)))
tree)
(export avl-lookup avl-add avlr-add avl-delete)
; three operations using eq to test
; (defun avlq-lookup (new-key tree order)
; (avl-lookup1 new-key tree order eq))
; (defun avlq-add (new-key tree order)
; (avl-add1 new-key tree order eq))
; (defun avlq-delete (new-key tree order)
; (avl-delete1 new-key tree order eq))
; (export avlq-lookup avlq-add avlq-delete)
; flatten tree into list of keys
(defun values-in-tree (tree) (values-in-tree1 (avl-tree-tree tree) nil))
(defun keys-in-tree (tree) (values-in-tree2 (avl-tree-tree tree) nil))
(export values-in-tree keys-in-tree)
; search tree for key satisfying predicate
(defun avl-lookup1 (new-key tree order predicate)
(cond
((null tree) nil)
((predicate new-key (avl-key tree))
(key-value-pair tree))
((order new-key (avl-key tree))
(avl-lookup1 new-key (avl-left tree) order predicate))
(t (avl-lookup1 new-key (avl-right tree) order predicate))))
; insert a new key into the tree
(defun avl-add1 (new-key tree order predicate)
(cond
((null tree)
(setq changed-height t)
(setq avl-result (make-key-value 'key new-key 'value nil))
(make-tree
'key-value-pair avl-result 'avl-left nil
'avl-right nil 'balance-state 0))
((predicate new-key (avl-key tree))
(setq changed-height nil)
(setq avl-result (key-value-pair tree))
tree)
((order new-key (avl-key tree))
((setter avl-left) tree
(avl-add1 new-key (avl-left tree) order predicate))
(cond
(changed-height
(cond
((avl-balanced tree)
(mark-left-unbalanced tree))
((avl-left-unbalanced tree)
(setq changed-height nil)
(mark-double-unbalanced tree)
(setq tree (rotate-right tree)))
(t
(setq changed-height nil)
(mark-balanced tree)))))
tree)
(t
((setter avl-right) tree
(avl-add1 new-key (avl-right tree) order predicate))
(cond (changed-height
(cond ((avl-balanced tree)
(mark-right-unbalanced tree))
((avl-right-unbalanced tree)
(setq changed-height nil)
(mark-double-unbalanced tree)
(setq tree (rotate-left tree)))
(t (setq changed-height nil)
(mark-balanced tree)))))
tree)))
; rebalance tree by left rotation (i.e. right child becomes root)
(defun rotate-left (tree)
(let ((r (avl-right tree)) (q ()))
(when (avl-left-unbalanced r) (setq r (rotate-right r)))
(setq q (avl-left r))
((setter avl-right) tree q)
((setter avl-left) r tree)
(cond
((avl-right-unbalanced r)
(if (avl-double-unbalanced tree)
(mark-balanced r)
(mark-left-unbalanced r))
(if (avl-right-unbalanced tree)
(mark-left-unbalanced tree)
(mark-balanced tree)))
(t
(mark-left-unbalanced r)
(mark-balanced tree)))
r))
; rebalance tree by left rotation (i.e. left child becomes root)
(defun rotate-right (tree)
(let ((l (avl-left tree)) (q ()))
(setq l (avl-left tree))
(when (avl-right-unbalanced l) (setq l (rotate-left l)))
(setq q (avl-right l))
((setter avl-left) tree q)
((setter avl-right) l tree)
(cond
((avl-left-unbalanced l)
(if (avl-double-unbalanced tree)
(mark-balanced l)
(mark-right-unbalanced l))
(if (avl-left-unbalanced tree)
(mark-right-unbalanced tree)
(mark-balanced tree)))
(t
(mark-right-unbalanced l)
(mark-balanced tree)))
l))
; remove key from tree
(defun avl-delete1 (new-key tree order predicate)
(cond
((null tree)
(setq changed-height nil)
(setq avl-result nil))
((predicate new-key (avl-key tree))
(cond ((null (avl-left tree))
(setq changed-height t)
(setq avl-result (key-value-pair tree))
(avl-right tree))
((null (avl-right tree))
(setq changed-height t)
(setq avl-result (key-value-pair tree))
(avl-left tree))
((avl-balanced tree) (avl-delete2 tree order predicate))
((avl-right-unbalanced tree)
(avl-delete1 new-key (rotate-left tree) order predicate))
(t (avl-delete1 new-key (rotate-right tree) order predicate))))
((order new-key (avl-key tree))
((setter avl-left) tree
(avl-delete1 new-key (avl-left tree) order predicate))
(when changed-height
(cond
((avl-balanced tree)
(setq changed-height nil)
(mark-right-unbalanced tree))
((avl-left-unbalanced tree)
(mark-balanced tree))
(t
(let ((r (avl-right tree)))
(when (avl-left-unbalanced r) (setq r (rotate-right r)))
((setter avl-right) tree (avl-left r))
((setter avl-left) r tree)
(cond
((avl-balanced r)
(setq changed-height nil)
(mark-left-unbalanced r))
(t
(mark-balanced r)
(mark-balanced tree)))
(setq tree r)))))
tree)
(t
((setter avl-right) tree
(avl-delete1 new-key (avl-right tree) order predicate))
(when changed-height
(cond
((avl-balanced tree)
(setq changed-height nil)
(mark-left-unbalanced tree))
((avl-right-unbalanced tree)
(mark-balanced tree))
(t
(let ((l (avl-left tree)))
(when (avl-right-unbalanced l) (setq l (rotate-left l)))
((setter avl-left) tree (avl-right l))
((setter avl-right) l tree)
(cond
((avl-balanced l)
(setq changed-height nil)
(mark-right-unbalanced l))
(t
(mark-balanced l)
(mark-balanced tree)))
(setq tree l)))))
tree)))
; used to deal with special case of when key to be deleted is the
; root of a balanced tree
(defun avl-delete2 (tree order predicate)
(let* ((r (avl-right tree)) (rl (avl-left r)))
(setq avl-result (key-value-pair tree))
(cond
((null rl)
((setter avl-left) r (avl-left tree))
(mark-left-unbalanced r)
(setq changed-height nil)
r)
(t
(setq rl (leftmost-key rl))
((setter avl-right) tree (avl-delete1 (car rl) r order predicate))
((setter key-value-pair) tree rl)
(when changed-height (mark-left-unbalanced tree))
tree))))
; go left as far as possible
(defun leftmost-key (tree)
(let ((l (avl-left tree)))
(if (null l) (key-value-pair tree) (leftmost-key l))))
; do in-order traversal constructing a list of the key-value pairs
; in each node
(defun values-in-tree1 (tree l)
(if (null tree)
l
(values-in-tree1
(avl-left tree)
(cons
(key-value-pair tree)
(values-in-tree1 (avl-right tree) l)))))
; do in-order traversal constructing a list of the keys in each node
(defun values-in-tree2 (tree l)
(if (null tree)
l
(values-in-tree2
(avl-left tree)
(cons
(avl-key tree)
(values-in-tree2 (avl-right tree) l)))))
)